home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / util / arcer / gnutar10.lha / GnuTAR / GNUTarSource.LHA / source / create.c < prev    next >
C/C++ Source or Header  |  1991-07-25  |  29KB  |  1,233 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  *
  25.  * @(#)create.c 1.36 11/6/87 - gnu
  26.  */
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/file.h>
  30. #include <stdio.h>
  31.  
  32. /* JF: this one is my fault */
  33. /* #include "utils.h" */
  34.  
  35. #ifndef V7
  36. #include <fcntl.h>
  37. #endif
  38.  
  39. #if !defined(MSDOS) && !defined(AMIGA)
  40. #include <pwd.h>
  41. #include <grp.h>
  42. #endif
  43.  
  44. #ifdef BSD42
  45. #include <sys/dir.h>
  46. #else
  47. #ifdef MSDOS
  48. #include <sys/dir.h>
  49. #else
  50. #ifdef USG
  51. #ifdef NDIR
  52. #include <ndir.h>
  53. #else
  54. #include <dirent.h>
  55. #endif
  56. #ifndef DIRECT
  57. #define direct dirent
  58. #endif
  59. #define DP_NAMELEN(x) strlen((x)->d_name)
  60. #else
  61. /*
  62.  * FIXME: On other systems there is no standard place for the header file
  63.  * for the portable directory access routines.    Change the #include line
  64.  * below to bring it in from wherever it is.
  65.  */
  66. #include "ndir.h"
  67. #endif
  68. #endif
  69. #endif
  70.  
  71. #ifndef DP_NAMELEN
  72. #define DP_NAMELEN(x)   (x)->d_namlen
  73. #endif
  74.  
  75. #ifdef USG
  76. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  77. #endif
  78.  
  79. /*
  80.  * V7 doesn't have a #define for this.
  81.  */
  82. #ifndef O_RDONLY
  83. #define O_RDONLY    0
  84. #endif
  85.  
  86. /*
  87.  * Most people don't have a #define for this.
  88.  */
  89. #ifndef O_BINARY
  90. #define O_BINARY    0
  91. #endif
  92.  
  93. #include "tar.h"
  94. #include "port.h"
  95.  
  96. extern union record *head;        /* Points to current tape header */
  97. extern struct stat hstat;        /* Stat struct corresponding */
  98. extern int head_standard;        /* Tape header is in ANSI format */
  99.  
  100. extern dev_t ar_dev;
  101. extern ino_t ar_ino;
  102.  
  103. /* JF */
  104. extern struct name *gnu_list_name;
  105.  
  106. /*
  107.  * If there are no symbolic links, there is no lstat().  Use stat().
  108.  */
  109. #ifndef S_IFLNK
  110. #define lstat stat
  111. #endif
  112.  
  113. extern char    *malloc();
  114. extern char    *strcpy();
  115. extern char    *strncpy();
  116. extern void    bzero();
  117. extern void    bcopy();
  118. extern int    errno;
  119.  
  120. extern void print_header();
  121.  
  122. union record *start_header();
  123. void finish_header();
  124. void finduname();
  125. void findgname();
  126. char *name_next();
  127. void to_oct();
  128. void dump_file();
  129.  
  130. static nolinks;         /* Gets set if we run out of RAM */
  131.  
  132. /*
  133.  * "Scratch" space to store the information about a sparse file before
  134.  * writing the info into the header or extended header
  135.  */
  136. /* struct sp_array     *sparsearray;*/
  137.  
  138. /* number of elts storable in the sparsearray */
  139. /*int    sparse_array_size = 10;*/
  140.  
  141. void
  142. create_archive()
  143. {
  144.     register char    *p;
  145.     char *name_from_list();
  146.  
  147.     open_archive(0);                /* Open for writing */
  148.  
  149.     if(f_gnudump) {
  150.         char buf[MAXNAMLEN],*q,*bufp;
  151.  
  152.         collect_and_sort_names();
  153.  
  154.         while(p=name_from_list())
  155.             dump_file(p,-1);
  156.         /* if(!f_dironly) { */
  157.             blank_name_list();
  158.             while(p=name_from_list()) {
  159.                 strcpy(buf,p);
  160. #ifdef AMIGA
  161.                 {
  162.                     short len = strlen(p) - 1;
  163.                     if (p[len] != '/' && p[len] != ':')
  164.                     strcat(buf,"/");
  165.                 }
  166.  
  167. #else
  168.                 if(p[strlen(p)-1]!='/')
  169.                     strcat(buf,"/");
  170. #endif
  171.                 bufp=buf+strlen(buf);
  172.                 for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
  173.                     if(*q=='Y') {
  174.                         strcpy(bufp,q+1);
  175.                         dump_file(buf,-1);
  176.                     }
  177.                 }
  178.             }
  179.         /* } */
  180.  
  181.     } else {
  182.         p = name_next(1);
  183.         if(!p)
  184.             dump_file(".", -1);
  185.         else {
  186.             do dump_file(p, -1);
  187.             while (p = name_next(1));
  188.         }
  189.     }
  190.  
  191.     write_eot();
  192.     close_archive();
  193.     name_close();
  194. }
  195.  
  196. /*
  197.  * Dump a single file.    If it's a directory, recurse.
  198.  * Result is 1 for success, 0 for failure.
  199.  * Sets global "hstat" to stat() output for this file.
  200.  */
  201. void
  202. dump_file (p, curdev)
  203.     char    *p;            /* File name to dump */
  204.     int    curdev;         /* Device our parent dir was on */
  205. {
  206.     union record    *header;
  207.     char type;
  208.     extern char *save_name;     /* JF for multi-volume support */
  209.     extern long save_totsize;
  210.     extern long save_sizeleft;
  211.     union record    *exhdr;
  212.     char save_linkflag;
  213.     extern time_t new_time;
  214.     int sparse_ind = 0;
  215.  
  216.  
  217.     if(f_confirm && !confirm("add",p))
  218.         return;
  219.  
  220.     /*
  221.      * Use stat if following (rather than dumping) 4.2BSD's
  222.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  223.      * systems, is #define'd to stat anyway.
  224.      */
  225.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  226.     {
  227. badperror:
  228.         msg_perror("can't add file %s",p);
  229. badfile:
  230.         errors++;
  231.         return;
  232.     }
  233.  
  234.     /* See if we only want new files, and check if this one is too old to
  235.        put in the archive. */
  236.     if(   f_new_files
  237.        && !f_gnudump
  238.        && new_time>hstat.st_mtime
  239.        && (hstat.st_mode&S_IFMT)!=S_IFDIR
  240.        && (f_new_files>1 || new_time>hstat.st_ctime)) {
  241.         if(curdev<0) {
  242.             msg("%s: is unchanged; not dumped",p);
  243.         }
  244.         return;
  245.     }
  246.  
  247.     /*
  248.      * See if we are crossing from one file system to another,
  249.      * and avoid doing so if the user only wants to dump one file system.
  250.      */
  251.     if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  252.         if(f_verbose)
  253.             msg("%s: is on a different filesystem; not dumped",p);
  254.         return;
  255.     }
  256.  
  257.     /* See if we are trying to dump the archive */
  258.     if(ar_dev && hstat.st_dev==ar_dev && hstat.st_ino==ar_ino) {
  259.         msg("%s is the archive; not dumped",p);
  260.         return;
  261.     }
  262.     /*
  263.      * Check for multiple links.
  264.      *
  265.      * We maintain a list of all such files that we've written so
  266.      * far.  Any time we see another, we check the list and
  267.      * avoid dumping the data again if we've done it once already.
  268.      */
  269.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  270.         register struct link    *lp;
  271.  
  272.     case S_IFREG:            /* Regular file */
  273. #ifdef S_IFCTG
  274.     case S_IFCTG:            /* Contigous file */
  275. #endif
  276. #ifdef S_IFCHR
  277.     case S_IFCHR:            /* Character special file */
  278. #endif
  279.  
  280. #ifdef S_IFBLK
  281.     case S_IFBLK:            /* Block     special file */
  282. #endif
  283.  
  284. #ifdef S_IFIFO
  285.     case S_IFIFO:            /* Fifo      special file */
  286. #endif
  287.  
  288.         /* First quick and dirty.  Hashing, etc later FIXME */
  289.         for (lp = linklist; lp; lp = lp->next) {
  290.             if (lp->ino == hstat.st_ino &&
  291.                 lp->dev == hstat.st_dev) {
  292.                 char *link_name = lp->name;
  293.  
  294.                 /* We found a link. */
  295.                 hstat.st_size = 0;
  296.                 header = start_header(p, &hstat);
  297.                 if (header == NULL) goto badfile;
  298.                 while(!f_absolute_paths && *link_name == '/') {
  299.                     static int link_warn = 0;
  300.  
  301.                     if (!link_warn) {
  302.                         msg("Removing leading / from absolute links");
  303.                         link_warn++;
  304.                     }
  305.                     link_name++;
  306.                 }
  307.                 strcpy(header->header.linkname,
  308.                     link_name);
  309.                 header->header.linkflag = LF_LINK;
  310.                 finish_header(header);
  311.         /* FIXME: Maybe remove from list after all links found? */
  312.                 return;     /* We dumped it */
  313.             }
  314.         }
  315.  
  316.         /* Not found.  Add it to the list of possible links. */
  317.         lp = (struct link *) malloc( (unsigned)
  318.             (strlen(p) + sizeof(struct link) - NAMSIZ));
  319.         if (!lp) {
  320.             if (!nolinks) {
  321.                 msg(
  322.     "no memory for links, they will be dumped as separate files");
  323.                 nolinks++;
  324.             }
  325.         }
  326.         lp->ino = hstat.st_ino;
  327.         lp->dev = hstat.st_dev;
  328.         strcpy(lp->name, p);
  329.         lp->next = linklist;
  330.         linklist = lp;
  331.     }
  332.  
  333.     /*
  334.      * This is not a link to a previously dumped file, so dump it.
  335.      */
  336.     switch (hstat.st_mode & S_IFMT) {
  337.  
  338.     case S_IFREG:            /* Regular file */
  339. #ifdef S_IFCTG
  340.     case S_IFCTG:            /* Contiguous file */
  341. #endif
  342.     {
  343.         int    f;        /* File descriptor */
  344.         long    bufsize, count;
  345.         long    sizeleft;
  346.         register union record    *start;
  347.         int    header_moved;
  348.         char    isextended = 0;
  349.         int    upperbound;
  350.         int    end_nulls = 0;
  351.  
  352.         header_moved = 0;
  353.  
  354. #ifdef BSD42
  355.         if (f_sparse_files) {
  356.         /*
  357.          * JK - This is the test for sparseness: whether the
  358.          * "size" of the file matches the number of blocks
  359.          * allocated for it.  If there is a smaller number
  360.          * of blocks that would be necessary to accommodate
  361.          * a file of this size, we have a sparse file, i.e.,
  362.          * at least one of those records in the file is just
  363.          * a useless hole.
  364.          */
  365.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  366.                 int    filesize = hstat.st_size;
  367.                 register int i;
  368.  
  369.                 printf("File is sparse: %s\n", p);
  370.                 header = start_header(p, &hstat);
  371.                 if (header == NULL)
  372.                     goto badfile;
  373.                 header->header.linkflag = LF_SPARSE;
  374.                 header_moved++;
  375.  
  376.             /*
  377.              * Call the routine that figures out the
  378.              * layout of the sparse file in question.
  379.              * UPPERBOUND is the index of the last
  380.              * element of the "sparsearray," i.e.,
  381.              * the number of elements it needed to
  382.              * describe the file.
  383.              */
  384.  
  385.                 upperbound = deal_with_sparse(p, header);
  386.  
  387.             /*
  388.              * See if we'll need an extended header
  389.              * later
  390.              */
  391.                 if (upperbound > SPARSE_IN_HDR-1)
  392.                     header->header.isextended++;
  393.             /*
  394.              * We store the "real" file size so
  395.              * we can show that in case someone wants
  396.              * to list the archive, i.e., tar tvf <file>.
  397.              * It might be kind of disconcerting if the
  398.              * shrunken file size was the one that showed
  399.              * up.
  400.              */
  401.                  to_oct((long) hstat.st_size, 1+12,
  402.                         header->header.realsize);
  403.  
  404.             /*
  405.              * This will be the new "size" of the
  406.              * file, i.e., the size of the file
  407.              * minus the records of holes that we're
  408.              * skipping over.
  409.              */
  410.  
  411.                 find_new_file_size(&filesize, upperbound);
  412.                 printf("File %s is now size %d\n",
  413.                             p, filesize);
  414.                 hstat.st_size = filesize;
  415.                 to_oct((long) filesize, 1+12,
  416.                         header->header.size);
  417. /*                to_oct((long) end_nulls, 1+12,
  418.                         header->header.ending_blanks);*/
  419.  
  420.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  421.                     if (!sparsearray[i].numbytes)
  422.                         break;
  423.                     to_oct(sparsearray[i].offset, 1+12,
  424.                         header->header.sp[i].offset);
  425.                     to_oct(sparsearray[i].numbytes, 1+12,
  426.                         header->header.sp[i].numbytes);
  427.                 }
  428.  
  429.             }
  430.         }
  431. #else
  432.         upperbound=SPARSE_IN_HDR-1;
  433. #endif
  434.  
  435.         sizeleft = hstat.st_size;
  436.         /* Don't bother opening empty, world readable files. */
  437.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  438.             f = open(p, O_RDONLY|O_BINARY);
  439.             if (f < 0) goto badperror;
  440.         } else {
  441.             f = -1;
  442.         }
  443.  
  444.         /* If the file is sparse, we've already taken care of this */
  445.         if (!header_moved) {
  446.             header = start_header(p, &hstat);
  447.             if (header == NULL) {
  448.                 if(f>=0)
  449.                     (void)close(f);
  450.                 goto badfile;
  451.             }
  452.         }
  453. #ifdef S_IFCTG
  454.         /* Mark contiguous files, if we support them */
  455.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  456.             header->header.linkflag = LF_CONTIG;
  457.         }
  458. #endif
  459.         isextended = header->header.isextended;
  460.         save_linkflag = header->header.linkflag;
  461.         finish_header(header);
  462.         if (isextended) {
  463.             int     sum = 0;
  464.             register int i;
  465. /*            register union record *exhdr;*/
  466.             int     arraybound = SPARSE_EXT_HDR;
  467.             /* static */ int index_offset = SPARSE_IN_HDR;
  468.  
  469.     extend:     exhdr = findrec();
  470.  
  471.             if (exhdr == NULL) goto badfile;
  472.             bzero(exhdr->charptr, RECORDSIZE);
  473.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  474.                 if (i+index_offset > upperbound)
  475.                     break;
  476.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  477.                     1+12,
  478.                     exhdr->ext_hdr.sp[i].numbytes);
  479.                 to_oct((long) sparsearray[i+index_offset].offset,
  480.                     1+12,
  481.                     exhdr->ext_hdr.sp[i].offset);
  482.             }
  483.             userec(exhdr);
  484. /*            sum += i;
  485.             if (sum < upperbound)
  486.                 goto extend;*/
  487.             if (index_offset+i < upperbound) {
  488.                 index_offset += i;
  489.                 exhdr->ext_hdr.isextended++;
  490.                 goto extend;
  491.             }
  492.  
  493.         }
  494.         if (save_linkflag == LF_SPARSE) {
  495.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  496.                 goto padit;
  497.         }
  498.         else
  499.           while (sizeleft > 0) {
  500.  
  501.             if(f_multivol) {
  502.                 save_name = p;
  503.                 save_sizeleft = sizeleft;
  504.                 save_totsize = hstat.st_size;
  505.             }
  506.             start = findrec();
  507.  
  508.             bufsize = endofrecs()->charptr - start->charptr;
  509.  
  510.             if (sizeleft < bufsize) {
  511.                 /* Last read -- zero out area beyond */
  512.                 bufsize = (int)sizeleft;
  513.                 count = bufsize % RECORDSIZE;
  514.                 if (count)
  515.                     bzero(start->charptr + sizeleft,
  516.                         (int)(RECORDSIZE - count));
  517.             }
  518.             count = read(f, start->charptr, bufsize);
  519.             if (count < 0) {
  520.                 msg_perror("read error at byte %ld, reading\
  521.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  522.                 goto padit;
  523.             }
  524.             sizeleft -= count;
  525.  
  526.             /* This is nonportable (the type of userec's arg). */
  527.             userec(start+(count-1)/RECORDSIZE);
  528.  
  529.             if (count == bufsize) continue;
  530.             msg( "file %s shrunk by %d bytes, padding with zeros.\n", p, sizeleft);
  531.             goto padit;        /* Short read */
  532.         }
  533.  
  534.         if(f_multivol)
  535.             save_name = 0;
  536.  
  537.         if (f >= 0)
  538.             (void)close(f);
  539.  
  540.         break;
  541.  
  542.         /*
  543.          * File shrunk or gave error, pad out tape to match
  544.          * the size we specified in the header.
  545.          */
  546.     padit:
  547.         while(sizeleft>0) {
  548.             save_sizeleft=sizeleft;
  549.             start=findrec();
  550.             bzero(start->charptr,RECORDSIZE);
  551.             userec(start);
  552.             sizeleft-=RECORDSIZE;
  553.         }
  554.         if(f_multivol)
  555.             save_name=0;
  556.         if(f>=0)
  557.             (void)close(f);
  558.         break;
  559. /*        abort(); */
  560.     }
  561.  
  562. #ifdef S_IFLNK
  563.     case S_IFLNK:            /* Symbolic link */
  564.     {
  565.         int size;
  566.  
  567.         hstat.st_size = 0;        /* Force 0 size on symlink */
  568.         header = start_header(p, &hstat);
  569.         if (header == NULL) goto badfile;
  570.         size = readlink(p, header->header.linkname, NAMSIZ);
  571.         if (size < 0) goto badperror;
  572.         if (size == NAMSIZ) {
  573.             msg("symbolic link %s too long\n",p);
  574.             break;
  575.         }
  576.         header->header.linkname[size] = '\0';
  577.         header->header.linkflag = LF_SYMLINK;
  578.         finish_header(header);          /* Nothing more to do to it */
  579.     }
  580.         break;
  581. #endif
  582.  
  583.     case S_IFDIR:            /* Directory */
  584.     {
  585.         register DIR *dirp;
  586.         register struct direct *d;
  587.         static char namebuf[NAMSIZ+2];
  588.         register int len;
  589.         int our_device = hstat.st_dev;
  590.  
  591.         /* Build new prototype name */
  592.         strncpy(namebuf, p, sizeof (namebuf));
  593.         len = strlen(namebuf);
  594.         while (len >= 1 && '/' == namebuf[len-1])
  595.             len--;            /* Delete trailing slashes */
  596. #ifdef AMIGA
  597.         if (len && namebuf[len-1] != ':')
  598.             namebuf[len++] = '/';
  599. #else
  600.         namebuf[len++] = '/';           /* Now add exactly one back */
  601. #endif
  602.         namebuf[len] = '\0';            /* Make sure null-terminated */
  603.  
  604.         /*
  605.          * Output directory header record with permissions
  606.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  607.          * If old archive format, don't write record at all.
  608.          */
  609.         if (!f_oldarch) {
  610.             hstat.st_size = 0;    /* Force 0 size on dir */
  611.             /*
  612.              * If people could really read standard archives,
  613.              * this should be:        (FIXME)
  614.             header = start_header(f_standard? p: namebuf, &hstat);
  615.              * but since they'd interpret LF_DIR records as
  616.              * regular files, we'd better put the / on the name.
  617.              */
  618.             header = start_header(namebuf, &hstat);
  619.             if (header == NULL)
  620.                 goto badfile;    /* eg name too long */
  621.  
  622.             if (f_gnudump)
  623.                 header->header.linkflag = LF_DUMPDIR;
  624.             else if (f_standard)
  625.                 header->header.linkflag = LF_DIR;
  626.  
  627.             /* If we're gnudumping, we aren't done yet so don't close it. */
  628.             if(!f_gnudump)
  629.                 finish_header(header);  /* Done with directory header */
  630.         }
  631.  
  632.         /* Hack to remove "./" from the front of all the file names */
  633.         if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/') {
  634.             len = 0;
  635.         }
  636.  
  637.         if(f_gnudump) {
  638.             int sizeleft;
  639.             int totsize;
  640.             int bufsize;
  641.             union record *start;
  642.             int count;
  643.             char *buf,*p_buf;
  644.  
  645.             buf=gnu_list_name->dir_contents; /* FOO */
  646.             totsize=0;
  647.             for(p_buf=buf;p_buf && *p_buf;) {
  648.                 int tmp;
  649.  
  650.                 tmp=strlen(p_buf)+1;
  651.                 totsize+=tmp;
  652.                 p_buf+=tmp;
  653.             }
  654.             totsize++;
  655.             to_oct((long)totsize,1+12,header->header.size);
  656.             finish_header(header);
  657.             p_buf=buf;
  658.             sizeleft=totsize;
  659.             while(sizeleft>0) {
  660.                 if(f_multivol) {
  661.                     save_name=p;
  662.                     save_sizeleft=sizeleft;
  663.                     save_totsize=totsize;
  664.                 }
  665.                 start=findrec();
  666.                 bufsize=endofrecs()->charptr - start->charptr;
  667.                 if(sizeleft<bufsize) {
  668.                     bufsize=sizeleft;
  669.                     count=bufsize%RECORDSIZE;
  670.                     if(count)
  671.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  672.                 }
  673.                 bcopy(p_buf,start->charptr,bufsize);
  674.                 sizeleft-=bufsize;
  675.                 p_buf+=bufsize;
  676.                 userec(start+(bufsize-1)/RECORDSIZE);
  677.             }
  678.             if(f_multivol)
  679.                 save_name = 0;
  680.             break;
  681.         }
  682.  
  683.         /* Now output all the files in the directory */
  684.         /* if (f_dironly)
  685.             break;        /* Unless the cmdline said not to */
  686.  
  687.  
  688.         errno = 0;
  689.         dirp = opendir(p);
  690.         if (!dirp) {
  691.             if (errno) {
  692.                 msg_perror ("can't open directory %s",p);
  693.             } else {
  694.                 msg("error opening directory %s",
  695.                     p);
  696.             }
  697.             break;
  698.         }
  699.  
  700.         /* Should speed this up by cd-ing into the dir, FIXME */
  701.         while (NULL != (d=readdir(dirp))) {
  702.             /* Skip . and .. */
  703.             if(is_dot_or_dotdot(d->d_name))
  704.                 continue;
  705.  
  706.             if (DP_NAMELEN(d) + len >= NAMSIZ) {
  707.                 namebuf[len]='\0';
  708.                 msg("file name %s%s too long\n",
  709.                     namebuf, d->d_name);
  710.                 continue;
  711.             }
  712.             strcpy(namebuf+len, d->d_name);
  713.             if(f_exclude && check_exclude(namebuf))
  714.                 continue;
  715.             dump_file(namebuf, our_device);
  716.         }
  717.  
  718.         closedir(dirp);
  719.     }
  720.         break;
  721.  
  722. #ifdef S_IFCHR
  723.     case S_IFCHR:            /* Character special file */
  724.         type = LF_CHR;
  725.         goto easy;
  726. #endif
  727.  
  728. #ifdef S_IFBLK
  729.     case S_IFBLK:            /* Block     special file */
  730.         type = LF_BLK;
  731.         goto easy;
  732. #endif
  733.  
  734. #ifdef S_IFIFO
  735.     case S_IFIFO:            /* Fifo      special file */
  736.  
  737.         type = LF_FIFO;
  738.         goto easy;
  739. #endif
  740.  
  741. #ifdef S_IFSOCK
  742.     case S_IFSOCK:            /* Socket    pretend its a fifo? */
  743.         type = LF_FIFO;
  744.         goto easy;
  745. #endif
  746.  
  747.     easy:
  748.         if (!f_standard) goto unknown;
  749.  
  750.         hstat.st_size = 0;        /* Force 0 size */
  751.         header = start_header(p, &hstat);
  752.         if (header == NULL) goto badfile;       /* eg name too long */
  753.  
  754.         header->header.linkflag = type;
  755.         if (type != LF_FIFO) {
  756.             to_oct((long) major(hstat.st_rdev), 8,
  757.                 header->header.devmajor);
  758.             to_oct((long) minor(hstat.st_rdev), 8,
  759.                 header->header.devminor);
  760.         }
  761.  
  762.         finish_header(header);
  763.         break;
  764.  
  765.     default:
  766.     unknown:
  767.         msg("%s: Unknown file type; file ignored.\n", p);
  768.         break;
  769.     }
  770. }
  771.  
  772. int
  773. finish_sparse_file(fd, sizeleft, fullsize, name)
  774.     int    fd;
  775.     long    *sizeleft,
  776.         fullsize;
  777.     char    *name;
  778. {
  779.     union record    *start;
  780.     static char    tempbuf[RECORDSIZE];
  781.     int        bufsize,
  782.             sparse_ind = 0,
  783.             count;
  784.     long        pos;
  785.  
  786.  
  787.  
  788.     while (*sizeleft > 0) {
  789.         start = findrec();
  790.         bzero(start->charptr, RECORDSIZE);
  791.         bufsize = sparsearray[sparse_ind].numbytes;
  792.         if (!bufsize) {  /* we blew it, maybe */
  793.             msg("Wrote %ld of %ld bytes to file %s",
  794.                    fullsize - *sizeleft, fullsize, name);
  795.             break;
  796.         }
  797.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  798.         /*
  799.          * If the number of bytes to be written here exceeds
  800.          * the size of the temporary buffer, do it in steps.
  801.          */
  802.         while (bufsize > RECORDSIZE) {
  803. /*            if (amt_read) {
  804.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  805.                 bufsize -= RECORDSIZE - amt_read;
  806.                 amt_read = 0;
  807.                 userec(start);
  808.                 start = findrec();
  809.                 bzero(start->charptr, RECORDSIZE);
  810.             }*/
  811.             /* store the data */
  812.             count = read(fd, start->charptr, RECORDSIZE);
  813.             if (count < 0)  {
  814.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s",
  815.                         fullsize - *sizeleft, bufsize, name);
  816.                 return 1;
  817.             }
  818.             bufsize -= count;
  819.             *sizeleft -= count;
  820.             userec(start);
  821.             start = findrec();
  822.             bzero(start->charptr, RECORDSIZE);
  823.         }
  824.  
  825.  
  826.         clear_buffer(tempbuf);
  827.         count = read(fd, tempbuf, bufsize);
  828.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  829.         if (count < 0)  {
  830.             msg_perror("read error at byte %ld, reading %d bytes, in file %s",
  831.                     fullsize - *sizeleft, bufsize, name);
  832.             return 1;
  833.         }
  834. /*        if (amt_read >= RECORDSIZE) {
  835.             amt_read = 0;
  836.             userec(start+(count-1)/RECORDSIZE);
  837.             if (count != bufsize) {
  838.                 msg("file %s shrunk by %d bytes, padding with zeros.\n", name, sizeleft);
  839.                 return 1;
  840.             }
  841.             start = findrec();
  842.         } else
  843.             amt_read += bufsize;*/
  844.         *sizeleft -= count;
  845.         userec(start);
  846.  
  847.     }
  848.     free(sparsearray);
  849. /*    userec(start+(count-1)/RECORDSIZE);*/
  850.     return 0;
  851.  
  852. }
  853.  
  854. init_sparsearray()
  855. {
  856.     register int i;
  857.  
  858.     sp_array_size = 10;
  859.     /*
  860.      * Make room for our scratch space -- initially is 10 elts long
  861.      */
  862.     sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
  863.     for (i = 0; i < sp_array_size; i++) {
  864.         sparsearray[i].offset = 0;
  865.         sparsearray[i].numbytes = 0;
  866.     }
  867. }
  868.  
  869.  
  870.  
  871. /*
  872.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  873.  * make a pass through the file and carefully note where any data is, i.e.,
  874.  * we want to find how far into the file each instance of data is, and how
  875.  * many bytes are there.  We store this information in the sparsearray,
  876.  * which will later be translated into header information.  For now, we use
  877.  * the sparsearray as convenient storage.
  878.  *
  879.  * As a side note, this routine is a mess.  If I could have found a cleaner
  880.  * way to do it, I would have.    If anyone wants to find a nicer way to do
  881.  * this, feel free.
  882.  */
  883. int
  884. deal_with_sparse(name, header, nulls_at_end)
  885.     char        *name;
  886.     union record    *header;
  887.  
  888. {
  889.     long    numbytes = 0;
  890.     long    offset = 0;
  891.     long    save_offset;
  892.     int    fd;
  893.     int    start,
  894.         end;
  895.     int    end_nulls = 0;
  896.     int    current_size = hstat.st_size;
  897.     int    sparse_ind = 0,
  898.         cc;
  899.     static char    buf[RECORDSIZE];
  900.     int    read_last_data = 0; /* did we just read the last record? */
  901.     int    amidst_data = 0;
  902.  
  903.     header->header.isextended = 0;
  904.     /*
  905.      * Can't open the file -- this problem will be caught later on,
  906.      * so just return.
  907.      */
  908.     if ((fd = open(name, O_RDONLY)) < 0)
  909.         return;
  910.  
  911.     init_sparsearray();
  912.     clear_buffer(buf);
  913.  
  914.     while ((cc = read(fd, buf, sizeof buf)) != 0) {
  915.  
  916.         if (sparse_ind > sp_array_size-1) {
  917.  
  918.         /*
  919.          * realloc the scratch area, since we've run out of room --
  920.          */
  921.             sparsearray = (struct sp_array *)
  922.                     realloc(sparsearray,
  923.                         2 * sp_array_size * (sizeof(struct sp_array)));
  924.             sp_array_size *= 2;
  925.         }
  926.         if (cc == sizeof buf) {
  927.             if (zero_record(buf)) {
  928.                 if (amidst_data) {
  929.                     sparsearray[sparse_ind++].numbytes
  930.                         = numbytes;
  931.                     amidst_data = 0;
  932.                     numbytes = 0;
  933.                 }
  934.                 offset += cc;
  935.             } else {  /* !zero_record(buf) */
  936.                 if (!amidst_data) {
  937.                     amidst_data = 1;
  938.                     where_is_data(&start, &end, buf);
  939.                     numbytes += end - start;
  940.                     offset += start;
  941.                     sparsearray[sparse_ind].offset = offset;
  942.                 } else
  943.                     numbytes += cc;
  944.                 offset += cc;
  945.             }
  946.         } else if (cc < sizeof buf) {
  947.             if (!zero_record(buf)) {
  948.                 if (!amidst_data) {
  949.                     amidst_data = 1;
  950.                     where_is_data(&start, &end, buf);
  951.                     /* In case there are nulls at the
  952.                        end that we need to remember */
  953.                     if (end < cc)
  954.                         end = cc;
  955.                     numbytes += start - end;
  956.                     offset += start;
  957. /*                    end_nulls = RECORDSIZE - end;*/
  958.                 } else {
  959.                     numbytes += cc;
  960. /*                    end_nulls = RECORDSIZE - end;*/
  961.                 }
  962.                 sparsearray[sparse_ind].numbytes = numbytes;
  963.             } /* else
  964.                 end_nulls = cc;*/
  965.         }
  966.         clear_buffer(buf);
  967.     }
  968.     if (numbytes)
  969.         sparsearray[sparse_ind].numbytes = numbytes;
  970.     close(fd);
  971. /*    printf("%d\n", end_nulls);
  972.     *nulls_at_end = end_nulls;*/
  973.  
  974.     return sparse_ind;
  975. }
  976.  
  977. /*
  978.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  979.  * data.
  980.  */
  981. clear_buffer(buf)
  982.     char    *buf;
  983. {
  984.     register int    i;
  985.  
  986.     for (i = 0; i < RECORDSIZE; i++)
  987.         buf[i] = '\0';
  988. }
  989.  
  990. /*
  991.  * JK -
  992.  * This routine takes a character array, and tells where within that array
  993.  * the data can be found.  It skips over any zeros, and sets the first
  994.  * non-zero point in the array to be the "start", and continues until it
  995.  * finds non-data again, which is marked as the "end."  This routine is
  996.  * mainly for 1) seeing how far into a file we must lseek to data, given
  997.  * that we have a sparse file, and 2) determining the "real size" of the
  998.  * file, i.e., the number of bytes in the sparse file that are data, as
  999.  * opposed to the zeros we are trying to skip.
  1000.  */
  1001. where_is_data(from, to, buffer)
  1002.     int    *from,
  1003.         *to;
  1004.     char    *buffer;
  1005. {
  1006.     register int    i = 0;
  1007.     register int    save_to = *to;
  1008.     int    amidst_data = 0;
  1009.  
  1010.  
  1011.     while (!buffer[i])
  1012.         i++;
  1013.     *from = i;
  1014.  
  1015.     if (*from < 16) /* don't bother */
  1016.         *from = 0;
  1017.     /* keep going to make sure there isn't more real
  1018.        data in this record */
  1019.     while (i < RECORDSIZE) {
  1020.         if (!buffer[i]) {
  1021.             if (amidst_data) {
  1022.                 save_to = i;
  1023.                 amidst_data = 0;
  1024.             }
  1025.             i++;
  1026.         }
  1027.         else if (buffer[i]) {
  1028.             if (!amidst_data)
  1029.                 amidst_data = 1;
  1030.             i++;
  1031.         }
  1032.     }
  1033.     if (i == RECORDSIZE)
  1034.         *to = i;
  1035.     else
  1036.         *to = save_to;
  1037.  
  1038. }
  1039.  
  1040. /*
  1041.  * Takes a recordful of data and basically cruises through it to see if
  1042.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1043.  * something that is a non-zero, i.e., useful data.
  1044.  */
  1045. zero_record(buffer)
  1046.     char    *buffer;
  1047. {
  1048.     register int    i;
  1049.  
  1050.     for (i = 0; i < RECORDSIZE; i++)
  1051.         if (buffer[i] != '\000')
  1052.             return 0;
  1053.     return 1;
  1054. }
  1055.  
  1056. find_new_file_size(filesize, highest_index)
  1057.     int    *filesize;
  1058.     int    highest_index;
  1059. {
  1060.     register int    i;
  1061.  
  1062.     *filesize = 0;
  1063.     for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1064.         *filesize += sparsearray[i].numbytes;
  1065. }
  1066.  
  1067. /*
  1068.  * Make a header block for the file  name  whose stat info is  st .
  1069.  * Return header pointer for success, NULL if the name is too long.
  1070.  */
  1071. union record *
  1072. start_header(name, st)
  1073.     char    *name;
  1074.     register struct stat *st;
  1075. {
  1076.     register union record *header;
  1077.  
  1078.     header = (union record *) findrec();
  1079.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1080.  
  1081.     /*
  1082.      * Check the file name and put it in the record.
  1083.      */
  1084.     if(!f_absolute_paths) {
  1085.         static int warned_once = 0;
  1086. #ifdef MSDOS
  1087.         if(name[1]==':') {
  1088.             name+=2;
  1089.             if(!warned_once++)
  1090.                 msg("Removing drive spec from names in the archive");
  1091.         }
  1092. #endif
  1093.         while ('/' == *name) {
  1094.             name++;             /* Force relative path */
  1095.             if (!warned_once++)
  1096.                 msg("Removing leading / from absolute path names in the archive.");
  1097.         }
  1098.     }
  1099.     strcpy(header->header.name, name);
  1100.     if (header->header.name[NAMSIZ-1]) {
  1101.         msg("%s: name too long\n", name);
  1102.         return NULL;
  1103.     }
  1104.  
  1105.     to_oct((long) (st->st_mode & ~S_IFMT),
  1106.                     8,  header->header.mode);
  1107.     to_oct((long) st->st_uid,       8,  header->header.uid);
  1108.     to_oct((long) st->st_gid,       8,  header->header.gid);
  1109.     to_oct((long) st->st_size,      1+12, header->header.size);
  1110.     to_oct((long) st->st_mtime,     1+12, header->header.mtime);
  1111.     /* header->header.linkflag is left as null */
  1112.     if(f_gnudump) {
  1113.         to_oct((long) st->st_atime, 1+12, header->header.atime);
  1114.         to_oct((long) st->st_ctime, 1+12, header->header.ctime);
  1115.     }
  1116.  
  1117. #ifndef NONAMES
  1118.     /* Fill in new Unix Standard fields if desired. */
  1119.     if (f_standard) {
  1120.         header->header.linkflag = LF_NORMAL;    /* New default */
  1121.         strcpy(header->header.magic, TMAGIC);   /* Mark as Unix Std */
  1122.         finduname(header->header.uname, st->st_uid);
  1123.         findgname(header->header.gname, st->st_gid);
  1124.     }
  1125. #endif
  1126.     return header;
  1127. }
  1128.  
  1129. /*
  1130.  * Finish off a filled-in header block and write it out.
  1131.  * We also print the file name and/or full info if verbose is on.
  1132.  */
  1133. void
  1134. finish_header(header)
  1135.     register union record *header;
  1136. {
  1137.     register int    i, sum;
  1138.     register char    *p;
  1139.     void bcopy();
  1140.  
  1141.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1142.  
  1143.     sum = 0;
  1144.     p = header->charptr;
  1145.     for (i = sizeof(*header); --i >= 0; ) {
  1146.         /*
  1147.          * We can't use unsigned char here because of old compilers,
  1148.          * e.g. V7.
  1149.          */
  1150.         sum += 0xFF & *p++;
  1151.     }
  1152.  
  1153.     /*
  1154.      * Fill in the checksum field.    It's formatted differently
  1155.      * from the other fields:  it has [6] digits, a null, then a
  1156.      * space -- rather than digits, a space, then a null.
  1157.      * We use to_oct then write the null in over to_oct's space.
  1158.      * The final space is already there, from checksumming, and
  1159.      * to_oct doesn't modify it.
  1160.      *
  1161.      * This is a fast way to do:
  1162.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1163.      */
  1164.     to_oct((long) sum,      8,  header->header.chksum);
  1165.     header->header.chksum[6] = '\0';        /* Zap the space */
  1166.  
  1167.     userec(header);
  1168.  
  1169.     if (f_verbose) {
  1170.         /* These globals are parameters to print_header, sigh */
  1171.         head = header;
  1172.         /* hstat is already set up */
  1173.         head_standard = f_standard;
  1174.         print_header();
  1175.     }
  1176.  
  1177.     return;
  1178. }
  1179.  
  1180.  
  1181. /*
  1182.  * Quick and dirty octal conversion.
  1183.  * Converts long "value" into a "digs"-digit field at "where",
  1184.  * including a trailing space and room for a null.  "digs"==3 means
  1185.  * 1 digit, a space, and room for a null.
  1186.  *
  1187.  * We assume the trailing null is already there and don't fill it in.
  1188.  * This fact is used by start_header and finish_header, so don't change it!
  1189.  *
  1190.  * This should be equivalent to:
  1191.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1192.  * except that sprintf fills in the trailing null and we don't.
  1193.  */
  1194. void
  1195. to_oct(value, digs, where)
  1196.     register long    value;
  1197.     register int    digs;
  1198.     register char    *where;
  1199. {
  1200.  
  1201.     --digs;             /* Trailing null slot is left alone */
  1202.     where[--digs] = ' ';            /* Put in the space, though */
  1203.  
  1204.     /* Produce the digits -- at least one */
  1205.     do {
  1206.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1207.         value >>= 3;
  1208.     } while (digs > 0 && value != 0);
  1209.  
  1210.     /* Leading spaces, if necessary */
  1211.     while (digs > 0)
  1212.         where[--digs] = ' ';
  1213.  
  1214. }
  1215.  
  1216.  
  1217. /*
  1218.  * Write the EOT record(s).
  1219.  * We actually zero at least one record, through the end of the block.
  1220.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1221.  */
  1222. write_eot()
  1223. {
  1224.     union record *p;
  1225.     int bufsize;
  1226.     void bzero();
  1227.  
  1228.     p = findrec();
  1229.     bufsize = endofrecs()->charptr - p->charptr;
  1230.     bzero(p->charptr, bufsize);
  1231.     userec(p);
  1232. }
  1233.